package com.maxcar.filter;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ReadListener;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.log4j.Logger;  
/** 
 * 过滤器把请求流保存起来 
 * 
 */  
public class SessionFilter implements Filter{  
  
    public void init(FilterConfig filterConfig) throws ServletException {  
          
    }  
  
    public void doFilter(ServletRequest request, ServletResponse response,  
            FilterChain chain) throws IOException, ServletException {  
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;  
        // 防止流读取一次后就没有了, 所以需要将流继续写出去  
        ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(httpServletRequest);  
        chain.doFilter(requestWrapper, response);  
    }  
  
    public void destroy() {  
          
    }  
  
    /** 
     * 保存流 
     *  
     * @author lyj 2015年12月16日 
     */  
    public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {  
        private Logger log = Logger.getLogger(this.getClass());  
  
        private final byte[] body;  
  
        public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {  
            super(request);  
            String sessionStream = getBodyString(request);  
            body = sessionStream.getBytes(Charset.forName("UTF-8"));  
            log.debug("保存的流" + sessionStream);  
        }  
  
        /** 
         * 获取请求Body 
         * 
         * @param request 
         * @return 
         */  
        public String getBodyString(final ServletRequest request) {  
            StringBuilder sb = new StringBuilder();  
            InputStream inputStream = null;  
            BufferedReader reader = null;  
            try {  
                inputStream = cloneInputStream(request.getInputStream());  
                reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));  
                String line = "";  
                while ((line = reader.readLine()) != null) {  
                    sb.append(line);  
                }  
            }  
            catch (IOException e) {  
                e.printStackTrace();  
            }  
            finally {  
                if (inputStream != null) {  
                    try {  
                        inputStream.close();  
                    }  
                    catch (IOException e) {  
                        e.printStackTrace();  
                    }  
                }  
                if (reader != null) {  
                    try {  
                        reader.close();  
                    }  
                    catch (IOException e) {  
                        e.printStackTrace();  
                    }  
                }  
            }  
            return sb.toString();  
        }  
  
        /** 
         * Description: 复制输入流</br> 
         *  
         * @param inputStream 
         * @return</br> 
         */  
        public InputStream cloneInputStream(ServletInputStream inputStream) {  
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();  
            byte[] buffer = new byte[1024];  
            int len;  
            try {  
                while ((len = inputStream.read(buffer)) > -1) {  
                    byteArrayOutputStream.write(buffer, 0, len);  
                }  
                byteArrayOutputStream.flush();  
            }  
            catch (IOException e) {  
                e.printStackTrace();  
            }  
            InputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());  
            return byteArrayInputStream;  
        }  
        @Override  
        public BufferedReader getReader() throws IOException {  
            return new BufferedReader(new InputStreamReader(getInputStream()));  
        }  
  
        @Override  
        public ServletInputStream getInputStream() throws IOException {  
  
            final ByteArrayInputStream bais = new ByteArrayInputStream(body);  
  
            return new ServletInputStream() {  
  
                @Override  
                public int read() throws IOException {  
                    return bais.read();  
                }  
  
                public boolean isFinished() {  
                    return false;  
                }  
  
                public boolean isReady() {  
                    return false;  
                }  
  
                public void setReadListener(ReadListener readListener) {  
  
                }  
            };  
        }  
    }  
}  